package com.authine.cloudpivot.ext.service.impl;


import com.authine.cloudpivot.engine.api.facade.BizObjectFacade;

import com.authine.cloudpivot.engine.api.facade.WorkflowInstanceFacade;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectCreatedModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectModel;
import com.authine.cloudpivot.engine.api.model.runtime.BizObjectQueryModel;
import com.authine.cloudpivot.engine.api.model.runtime.WorkItemModel;
import com.authine.cloudpivot.engine.component.query.api.Page;
import com.authine.cloudpivot.engine.component.query.api.helper.PageableImpl;
import com.authine.cloudpivot.engine.domain.runtime.BizWorkitem;
import com.authine.cloudpivot.ext.service.OaToFacade;
import com.authine.cloudpivot.ext.util.ItemTypeUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author hxd
 * @Date 2021/11/26 10:42
 * @Description
 **/
@Service
@Transactional
public class OaToFacadeImpl implements OaToFacade {

    @Autowired
    BizObjectFacade bizObjectFacade;

    @Autowired
    WorkflowInstanceFacade instanceFacade;
    @Autowired
    OaWorkItemServiceImpl oaWorkItemService;

//    @Autowired
//    MessagePushServiceImpl messagePushService;


    private String settingSchemaCode = "oatodosetting";

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public Map<String, Object> reSend(String userId,String oaTodoId) {

        Map<String, Object> restMap = new HashMap<>();

        BizObjectCreatedModel bizObject = bizObjectFacade.getBizObject("oaTodoOpt",oaTodoId);
        restMap.put("code","1");

        if (bizObject == null) {
            restMap.put("msg", "todo 数据不存在");
        } else {

            String rst = bizObject.getString("rst");

            if (!rst.equals("失败")){
                restMap.put("msg","已成功的数据不需要操作");
                return restMap;
            }

            String itemId = bizObject.getString("itemId");
            String itemType = bizObject.getString("itemType");
            WorkItemModel item =null;
            if (ItemTypeUtils.db.equals(itemType)){
                 item = instanceFacade.getWorkItem(itemId);
            }else if(ItemTypeUtils.yb.equals(itemType)){
                item = instanceFacade.getFinishedWorkItem(itemId);
            }
            if (item == null) {
                restMap.put("msg","发送待办数据不存在,或已审批完成");
                restMap.put("code","0");
                bizObject.put("rst","成功");
                bizObject.put("msg","推送成功");
            }else{
                boolean flag = false;
                try {
                    if (ItemTypeUtils.db.equals(itemType)){
                        flag = oaWorkItemService.sendTodo(item,getOaAppName(item.getAppCode()));
                    }else if(ItemTypeUtils.yb.equals(itemType)){
                        flag = oaWorkItemService.deleteToDo(item.getId());
                    }
                } catch (Exception e) {
                    restMap.put("msg",e.getMessage());
                    bizObject.put("msg",e.getMessage());
                }

                if (flag){
                    bizObject.put("rst","成功");
                }
            }

            bizObjectFacade.saveBizObject(userId, bizObject,false);
        }

        return restMap;
    }

    private final static String OA_TO_DO_SETTING =   "oatodosetting";

    private static boolean FRIST_LOAD = true;

    public String getOaAppName(String appCode){

        BoundHashOperations oatodosetting = redisTemplate.boundHashOps("oatodosetting");
        Object val = oatodosetting.get(appCode);
        if (val == null ){

            Boolean hasKey = redisTemplate.hasKey("oatodosetting");

            if (FRIST_LOAD || !hasKey){
                FRIST_LOAD = false;
                loadOaTodoSetting();
                val = oatodosetting.get(appCode);
            }
        }
        return  val==null? null:String.valueOf(val);
    }



    public void loadOaTodoSetting(){

        BizObjectQueryModel queryModel = new BizObjectQueryModel();
        queryModel.setSchemaCode(settingSchemaCode);
        queryModel.setQueryCode(settingSchemaCode);
        queryModel.setPageable(new PageableImpl(0, 100));
        Page<BizObjectModel> modelPage = bizObjectFacade.queryBizObjects(queryModel);

        if(modelPage.getTotal()>0){
            Map<String, String> appMap = modelPage.getContent().stream()
                    .collect(Collectors.toMap(a -> a.getString("appCode")
                            , a -> a.getString("todoAppName"),
                            (k1, k2) -> k1));


            if (!appMap.isEmpty()){

                BoundHashOperations<String,String,String> hashOps = redisTemplate.boundHashOps(OA_TO_DO_SETTING);

                Set<String> keys = hashOps.keys();

                Set<String> appKeys = appMap.keySet();

                Set<String> collect = keys.stream().filter(a -> !appKeys.contains(a)).collect(Collectors.toSet());

                if(!collect.isEmpty()){
                    hashOps.delete(collect.toArray());
                }

                hashOps.putAll(appMap);
            }
        }else{
            redisTemplate.delete(OA_TO_DO_SETTING);
        }

    }

}
